home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Programming / A68k / Codegen.c < prev    next >
C/C++ Source or Header  |  1991-04-16  |  27KB  |  890 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*            MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*                Copyright 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*              Object code generator - April 16, 1991            */
  8. /*                                    */
  9. /*   This program may be copied for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on all copies of the source code.  Copying for any other use   */
  12. /*   without the consent of the author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr. Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*     AmigaDOS conversion copyright 1991 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include "A68kdef.h"
  24. #include "A68kglb.h"
  25.  
  26.  
  27.  
  28. void GetObjectCode (dummy) int dummy;
  29. /* Determines the object code for the operation as well as the operands */
  30. /* Returns each (up to 3 fields), along with the length of each.     */
  31. {
  32.     int  quick;
  33.     int  ExtL;        /* Bit pattern for instruction extension word */
  34.     long templong;
  35.     char tempop[MAXLINE];
  36.     register int i, j;
  37.  
  38.     i = Instructions (OpLoc);        /* Analyze the opcode. */
  39.  
  40.     if (Dir != None) {
  41.     ObjDir (dummy);            /* Process directives. */
  42.     return;
  43.     }
  44.     if ((Label[0] != '\0') || (OpCode[0] != '\0'))
  45.     PrntAddr = TRUE;        /* Print address, at least. */
  46.  
  47.     if (OpCode[0] == '\0') {
  48.     MakeHunk |= PrntAddr;
  49.     return;                /* No opcode, exit now. */
  50.     }
  51.     if (!i) {                /* Unrecognized opcode */
  52.     if ((Quiet < 0) && (InF->UPtr == 0))
  53.         ShowLine (InF->Line);    /* Show where we are. */
  54.     if (OpCode[0] == '*') {
  55.         Error (OpLoc, NoCode);    /* Don't try to open the console! */
  56.         return;
  57.     }
  58.     if (Size == Byte)        /* Set up \0 parameter. */
  59.         MacSize[0] = 'B';
  60.     else if (Size == Long)
  61.         MacSize[0] = 'L';
  62.     else
  63.         MacSize[0] = 'W';
  64.  
  65.     AddrAdv = InstSize = 0;
  66.     PrntAddr = FALSE;
  67.     Dir = MacCall;            /* Assume it's a macro call. */
  68.     tempop[0] = ' ';
  69.     tempop[1] = '\0';
  70.     strcat (tempop, OpCode);    /* Prepend a blank to OpCode. */
  71.     if (ReadSymTab (tempop)) {    /* Search for user macro. */
  72.         AddRef (LineCount);
  73.         if (InF->UPtr == 0) {    /* If we're reading from a file */
  74.         InF->Pos = lseek (In.fd, 0L,1); /*  remember where we are. */
  75.         InF->Pos -= In.Lim - In.Ptr;
  76.         }
  77.         if(Sym->Defn < LineCount) {    /* Only if previously defined! */
  78.         InFNum++;
  79.         if (--InF < LowInF)
  80.             LowInF = InF;
  81.         MacCount++;
  82.         Heap2Space (0);            /* Check for space. */
  83.         InF->UPtr = (char *) Hunk2;    /* MACRO statement */
  84.         InF->UPtr += strlen(InF->UPtr) + 1; /* Skip over it. */
  85.         InF->NPtr = NextFNS;    /* New stack pointer */
  86.         InF->Line = 0;        /* Line number in macro */
  87.         InF->NArg=GetArgs (""); /* Get arguments. */
  88.         InF->MCnt = MacCount;    /* Macro number */
  89.         if (OuterMac == 0)
  90.             OuterMac = InFNum;    /* Outer macro */
  91.         return;
  92.         }
  93.     }
  94.     if (!OpenIncl (OpCode, InclList)) {
  95.         Error (OpLoc, NoCode);    /* Couldn't open file. */
  96.         Dir = BadMac;        /* Invalid macro */
  97.         return;            /* Return to outer file. */
  98.     }
  99.     InFNum++;            /* Bump nesting level. */
  100.     if (--InF < LowInF)
  101.         LowInF = InF;
  102.     InF->UPtr = 0;            /* Not a user macro. */
  103.     InF->NPtr = NextFNS;        /* New stack pointer */
  104.     InF->Line = 0;            /* Line number in macro */
  105.     InF->MCnt = MacCount;        /* Macro number */
  106.     MacCount++;
  107.     Heap2Space (0);            /* Check for space. */
  108.     InF->NArg = GetArgs (OpCode);    /* Get arguments. */
  109.     if (OuterMac == 0)
  110.         OuterMac = InFNum;        /* Outer macro */
  111.     return;
  112.     }
  113.  
  114.     MakeHunk = TRUE;            /* We have something for a hunk. */
  115.     AddrCnt = AddrBndW (AddrCnt);    /* It'll be word-aligned. */
  116.  
  117.     if ((AdrModeA != 0) || (AdrModeB != 0)) {
  118.     Src.Loc = SrcLoc;
  119.     Dest.Loc = DestLoc;
  120.     if (SrcPC IN AdrModeB)    /* Source operand can be PC-relative. */
  121.         if (EA05z IN AdrModeB)
  122.         i = 4;        /* Displacement offset is 4 for MOVEM. */
  123.         else
  124.         i = 2;        /* Offset is 2 for all others. */
  125.     else
  126.         i = 0;        /* PC-relative modes are not allowed. */
  127.     GetOperand (SrcOp, &Src, i);
  128.     GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0);
  129.     }
  130.     if ((EA05z IN AdrModeB) && !NoOpt) {    /* MOVEM */
  131.     if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
  132.         if (Src.Mode == Imm) {    /* Assume source is a register mask. */
  133.         j = 0;    /* Flip it since A68k will flip it back again later. */
  134.         for (i = 0; i < 16; i++)
  135.             if (Src.Value & (1<<i))
  136.             j |= (1 << (15-i));
  137.         Src.Value = j;
  138.         Src.Mode = MultiM;
  139.         } else if (Dest.Mode == Imm) {
  140.         Dest.Mode = MultiM;    /* Assume dest. is a register mask. */
  141.         } else {
  142.         OpCode[4] = '\0';    /* MOVEM of a single register */
  143.         Instructions (OpLoc);    /*  becomes a straight MOVE.  */
  144.         }
  145.     }
  146.     }
  147.     if ((Src.Mode == Imm)        /* Immediate instructions */
  148.     && (Src.Hunk == ABSHUNK) && (Src.Defn < LineCount)
  149.     && !NoOpt
  150.     &&     (((EA611 IN AdrModeB) && (Dest.Mode == DReg)    /* MOVE */
  151.         && (Size == Long) && (Src.Value >= -128) && (Src.Value <= 127))
  152.     || ((EA05y IN AdrModeB)                /* ADD/SUB */
  153.         && (Src.Value > 0) && (Src.Value <= 8)))) {
  154.         strcat (OpCode, "Q");   /* Make it ADDQ/SUBQ/MOVEQ. */
  155.         Instructions (OpLoc);
  156.     }
  157.     else if ((Dest.Mode == ARDir) && (Src.Mode <= 12)
  158.     && (((EA05y | EA611) IN AdrModeB)    /* ADD, SUB, or MOVE */
  159.     || (OpM68C IN AdrModeA))) {    /* CMP */
  160.         strcat (OpCode, "A");       /* ADD op,An becomes ADDA etc. */
  161.         Instructions (OpLoc);
  162.     }
  163.     else if ((Src.Mode == Imm)        /* Immediate instructions */
  164.     && ((OpM68D | OpM68C | OpM68X) IN AdrModeA)) {
  165.     strcat (OpCode, "I");           /* ADD/AND/OR/SUB, CMP, EOR */
  166.     Instructions (OpLoc);        /* ADD #op,d becomes ADDI etc. */
  167.     }
  168.     else if ((Src.Mode == ARPost) && (Dest.Mode == ARPost)
  169.     && (OpM68C IN AdrModeA)) {        /* CMP */
  170.     strcat (OpCode, "M");           /* Generate CMPM if necessary. */
  171.     Instructions (OpLoc);
  172.     }
  173.  
  174.  
  175. /*=================== Operand validation routines ====================*/
  176.  
  177.     if (Pass2) {
  178.  
  179.     /* If an immediate operand isn't absolute, it must be a long word. */
  180.  
  181.     if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK))
  182.         Error (SrcLoc, RelErr);
  183.  
  184.     /* ------- Check for instructions with too many operands. ------- */
  185.     /* Some specialized instruction routines contain their own tests. */
  186.  
  187.     if (AdrModeA == 0) {        /* Should have only one operand. */
  188.         if ((AdrModeB == EA05e) || (AdrModeB == (Size67 | EA05e))) {
  189.         if (Dest.Mode != Null)
  190.             Error (DestLoc, OperErr);
  191. /*        } else if (AdrModeB == 0) { */  /* Should have no operands. */
  192. /*        if (Src.Mode != Null)
  193.             Error (SrcLoc, OperErr);
  194.         if (Dest.Mode != Null)
  195.             Error (DestLoc, OperErr); De-activated for now */
  196.         }
  197.     }
  198.     if ((AdrModeA != 0) || (AdrModeB != 0)) {
  199.         if(Dest.Mode != NULL) { /* We should never find 3 operands. */
  200.         j = DestLoc + strlen (DestOp);
  201.         if ((Line[j] != '\0')
  202.         && (Line[j] != ';')
  203.         && (!isspace (Line[j]))) {
  204.             Error (j, OperErr);
  205.         }
  206.         }
  207.  
  208.     /* ---------------- Check for missing operands. ----------------- */
  209.  
  210.         if (Src.Mode == Null) {
  211.         Error (OpLoc+strlen(OpCode), OperErr);    /* No source */
  212.         } else if (Dest.Mode == Null) {
  213.         if (((ImmMode & AdrModeB) == ImmMode)
  214.         || (TwoOpsA IN AdrModeA)
  215.         || (TwoOpsB IN AdrModeB)) {
  216.             Error (SrcLoc+strlen(SrcOp), OperErr);  /* No dest. */
  217.         }
  218.         }
  219.     }
  220.     }
  221.  
  222. /*====================================================================*/
  223.  
  224.     /* ---------------- Decrement and Branch (DBcc) ----------------- */
  225.  
  226.     if (DecBr IN AdrModeA) {
  227.     if (Pass2) {
  228.         if (Src.Mode != DReg)
  229.         Error (SrcLoc, ModeErr);
  230.         if (Dest.Value & 1)
  231.         Error (DestLoc, AlignErr);  /* Boundary alignment error */
  232.  
  233.         if (Dest.Hunk == CurrHunk) {
  234.         ObjSrc = Dest.Value-AddrCnt-2;    /* Relative branch distance */
  235.         Dest.Hunk = ABSHUNK;        /* Displacement is absolute */
  236.         } else
  237.         ObjSrc = Dest.Value;    /* Let the linker worry about it. */
  238.  
  239.         if ((ObjSrc > 32767) || (ObjSrc < -32768))
  240.         Error (DestLoc,BraErr);    /* Too far to branch */
  241.  
  242.         if (Dest.Hunk!=CurrHunk) {    /* DBcc to another section */
  243.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  244.         PutRel (templong, Dest.Hunk, 2);
  245.         }
  246.         ObjOp = Op | Src.Rn;
  247.     }
  248.     AddrAdv = 4;
  249.     nO = nS = 2;
  250.     return;
  251.     }
  252.  
  253.     /* ------------ Branch (Bcc, including BRA and BSR) ------------- */
  254.  
  255.     if (Brnch IN AdrModeA) {
  256.     if (Src.Value & 1)
  257.         Error (SrcLoc, AlignErr);    /* Boundary alignment error */
  258.  
  259.     if (!Pass2 && !NoOpt && (Size != Byte)) {
  260.         if ((Src.Defn < LineCount)    /* Backward branch */
  261.         && (Src.Hunk == CurrHunk)) {
  262.         ObjSrc = Src.Value-AddrCnt-2;    /* Relative branch distance */
  263.         Src.Hunk = ABSHUNK;        /* Displacement is absolute. */
  264.         if ((ObjSrc != 0) && (ObjSrc >= -128) && (ObjSrc <= 127)) {
  265.             Size = Byte;    /* Convert to a short branch. */
  266.             if ((char *) FwdLim2 >= ((char *) FwdCurr + FWDSIZE)) {
  267.             FwdCurr->Link =    /* Get a new chunk. */
  268.                 (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  269.             if (FwdCurr->Link == NULL)
  270.                 quit_cleanup ("Out of memory!\n");
  271.             FwdCurr = FwdCurr->Link;
  272.             FwdCurr->Link = NULL;
  273.             FwdLim2 = (int *)
  274.                 ((char *) FwdCurr + sizeof (struct FwdTable *));
  275.             }
  276.             *FwdLim2++ = LineCount;    /* Flag branch in pass 2. */
  277.         }
  278.         } else if (Src.Single && (Src.Defn == NODEF)) {    /* Forward */
  279.         if (!ReadSymTab (SrcOp))     /* Store candidate target. */
  280.             AddSymTab (SrcOp, 0L, (long)ABSHUNK, NODEF, 0);
  281.         PackFwdBranch (dummy);    /* Drop expired entries. */
  282.         FwdLim1->Loc = AddrCnt;    /* Location of candidate */
  283.         FwdLim1->FwdSym = Sym;    /* Symbol table entry for target */
  284.         FwdLim1->Line = LineCount;    /* Line number */
  285.         FwdLim1++;
  286.         }
  287.     }
  288.  
  289.     if (Pass2 && !NoOpt && (Size != Byte)) {    /* Pass 2 */
  290.         FwdCurr = FwdStart;    /* Scan the entire foward branch table. */
  291.         FwdPtr = (int *) ((char *) FwdCurr + sizeof (struct FwdTable *));
  292.         while (FwdPtr != FwdLim2) {
  293.         if (*FwdPtr == LineCount) {    /* We flagged it in pass 1. */
  294.             Size = Byte;    /* Make it a short branch */
  295.             break;
  296.         } else {
  297.             FwdPtr++;        /* Scan forward in table. */
  298.             if (FwdPtr == FwdLim2)
  299.             break;
  300.             if ((char *) FwdPtr >= ((char *) FwdCurr + FWDSIZE)) {
  301.             FwdCurr = FwdCurr->Link;    /* Next chunk */
  302.             FwdPtr = (int *)
  303.                 ((char *) FwdCurr + sizeof (struct FwdTable *));
  304.             }
  305.         }
  306.         }
  307.     }
  308.     if (Src.Hunk == CurrHunk) {
  309.         ObjSrc=Src.Value-AddrCnt-2;    /* Relative branch distance */
  310.         Src.Hunk = ABSHUNK;        /* Displacement is absolute. */
  311.         if ((Size == Byte) && (ObjSrc == 0))
  312.         Error (SrcLoc, BccSDsp0);    /* Can't do this! */
  313.         if (Pass2 && FwdProc && (Size != Byte) 
  314.         && (ObjSrc >= -128) && (ObjSrc <= 129) && (ObjSrc != 2))
  315.         FwdShort=TRUE;    /* Forward reference could be made short. */
  316.     } else {
  317.         ObjSrc = Src.Value;        /* Let the linker worry about it. */
  318.         if (Size == Byte)
  319.         Error (SrcLoc, BraErr);    /* No external short branches! */
  320.     }
  321.  
  322.     if (Size != Byte) {
  323.         InstSize = 4;
  324.         nS = 2;
  325.         templong = 32767;
  326.     } else {
  327.         InstSize = 2;
  328.         Op |= (ObjSrc & 0x00FF);
  329.         templong = 127;
  330.     }
  331.     if ((ObjSrc > templong) || (ObjSrc < -templong-1))
  332.         Error (SrcLoc, BraErr);    /* Too far to branch */
  333.  
  334.     if (Dest.Mode != Null)
  335.         Error (DestLoc, OperErr);    /* No Destination operand! */
  336.  
  337.     AddrAdv = InstSize;
  338.     ObjOp = Op;
  339.     nO = 2;
  340.     if (Src.Hunk != CurrHunk) {    /* Bcc to another section */
  341.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  342.         PutRel (templong, Src.Hunk, 2);
  343.     }
  344.     return;
  345.     }
  346.  
  347.     /* --------------- JSR.S and BSR.S are not valid! --------------- */
  348.  
  349.     if (((Op == JMP) || (Op == JSR)) && (Size == Byte))
  350.     Error (OpLoc + 4, SizeErr);
  351.  
  352. /*  Uses information from Instructions & GetOperand (among others)  */
  353. /*  to complete calculation of Object Code.                         */
  354. /*  Op, AdrModeA, AdrModeB, Size, and Src & Dest records are all    */
  355. /*  Global variables imported from the SyntaxAnalyzer MODULE.       */
  356.  
  357.     ExtL = 0;
  358.     quick = FALSE;
  359.  
  360.     /* Ignore size specification on BCHG, BCLR, BSET, and BTST. */
  361.  
  362.     if (Bit811 IN AdrModeB)
  363.     Size = Word;
  364.  
  365.     /* ------------ Check for boundary alignment errors. ------------ */
  366.     /*  BCHG, BCLR, BSET, BTST, LEA, NBCD, PEA, Scc, TAS are exempt.  */
  367.  
  368.     if (Pass2) {
  369.     if ((Size != Byte)
  370.     && (Op != LEA)
  371.     && (Op != PEA)
  372.     && !((AdrModeA == 0) && (AdrModeB == 0))
  373.     && !(AdrModeB & EA05c)        /* BTST */
  374.     && !((AdrModeB&EA05e) && (AdrModeA==0) && !(AdrModeB&Size67))) {
  375.         if (Src.Value & 1)
  376.         if ((Src.Mode >= ARDisp) && (Src.Mode <= PCDisX))
  377.             Error (SrcLoc, AlignErr);
  378.         if (Dest.Value & 1)
  379.         if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX))
  380.             Error (DestLoc, AlignErr);
  381.     }
  382.  
  383. /* Check for special cases first */
  384.  
  385.     if (Op == STOP) {
  386.         if (Src.Mode != Imm)
  387.         Error (SrcLoc, ModeErr);
  388.         if (Dest.Mode != Null)
  389.         Error (DestLoc, OperErr);
  390.     }
  391.  
  392.     if (Op == LINK) {
  393.         Op |= Src.Rn;
  394.         if (Src.Mode != ARDir)
  395.         Error (SrcLoc, ModeErr);
  396.         if (Dest.Mode != Imm)
  397.         Error (DestLoc, ModeErr);
  398.         else if (Dest.Value & 1)
  399.         Error (DestLoc, AlignErr);  /* Boundary alignment error */
  400.     }
  401.  
  402.     if (Op == SWAP) {
  403.         if (!(EA05f IN AdrModeB)) {    /* Ignore if PEA instruction. */
  404.         Op |= Src.Rn;
  405.         if (Src.Mode != DReg)
  406.             Error (SrcLoc, ModeErr);
  407.         if (Dest.Mode != Null)
  408.             Error (DestLoc, OperErr);
  409.         }
  410.     }
  411.  
  412.     if (Op == UNLK) {
  413.         Op |= Src.Rn;
  414.         if (Src.Mode != ARDir)
  415.         Error (SrcLoc, ModeErr);
  416.         if (Dest.Mode != Null)
  417.         Error (DestLoc, OperErr);
  418.     }
  419.  
  420. /* Now do generalized address modes */
  421.  
  422.     if ((Ry02 IN AdrModeA)&&(Rx911 IN AdrModeA)) {    /* Two registers */
  423.         if (Op == CMPM) {        /* Special routine for CMPM */
  424.         Op |= Src.Rn | (Dest.Rn << 9);
  425.         if (Src.Mode != ARPost)
  426.             Error (SrcLoc, ModeErr);
  427.         if (Dest.Mode != ARPost)
  428.             Error (DestLoc, ModeErr);
  429.         } else {        /* Other two-register instructions */
  430.         Op |= Src.Rn | (Dest.Rn << 9);
  431.         if (RegMem3 IN AdrModeA) {
  432.             if (Src.Mode == DReg) {
  433.             if (Dest.Mode != DReg)
  434.                 Error (DestLoc, ModeErr);
  435.             } else if (Src.Mode == ARPre) {
  436.             Op |= 0x0008;
  437.             if (Dest.Mode != ARPre)
  438.                 Error (DestLoc, ModeErr);
  439.             } else
  440.             Error (SrcLoc, OperErr);
  441.         } else {
  442.             if (Src.Mode == ARPost)
  443.             if (Dest.Mode != ARPost)
  444.                 Error (DestLoc, ModeErr);
  445.             else
  446.                 Error (SrcLoc, OperErr);
  447.         }
  448.         }
  449.     }
  450.     }
  451.     if (Data911 IN AdrModeA) {        /* Data in 9-11 (ADDQ/SUBQ) */
  452.     quick = TRUE;
  453.     if (Src.Mode == Imm)
  454.         if ((Src.Value > 0) && (Src.Value <= 8)) {
  455.         if (Src.Value < 8)    /* Data of 8 is coded as 000. */
  456.             Op |= Src.Value << 9;
  457.         } else
  458.         Error (SrcLoc, SizeErr);
  459.     else
  460.         Error (SrcLoc, ModeErr);
  461.     }
  462.  
  463.     if (CntR911 IN AdrModeA) {        /* Only Shift and Rotate use this. */
  464.     if (Dest.Mode == DReg) {
  465.         Op = (Op & 0xF9FF) | Dest.Rn;
  466.         if (Size == Word) Op |= 0x0040;
  467.         if (Size == Long) Op |= 0x0080;
  468.         if (Src.Mode == DReg)
  469.         Op |= 0x0020 | (Src.Rn << 9);
  470.         else if (Src.Mode == Imm) {
  471.         quick = TRUE;
  472.         if ((Src.Value > 0) && (Src.Value <= 8)) { /* Range check */
  473.             if (Src.Value < 8)    /* Data of 8 is coded as 000. */
  474.             Op |= (Src.Value << 9);
  475.         } else
  476.             Error (SrcLoc, SizeErr);
  477.         } else
  478.         Error (SrcLoc, OperErr);
  479.     } else if (Dest.Mode == Null) {
  480.         Op = (Op & 0xFFE7) | 0x00C0;
  481.         EffAdr (&Src, (mea | aea));
  482.     } else
  483.         Error (SrcLoc, ModeErr);
  484.     }
  485.  
  486.     if (Data03 IN AdrModeA) {        /* TRAP Vector in 0-3 */
  487.     quick = TRUE;
  488.     if (Src.Mode == Imm)
  489.         if ((Src.Value >= 0) && (Src.Value < 16))
  490.         Op |= Src.Value;
  491.         else
  492.         Error (SrcLoc, SizeErr);
  493.     else
  494.         Error (SrcLoc, ModeErr);
  495.  
  496.     if (Dest.Mode != Null)
  497.         Error (DestLoc, OperErr);
  498.     }
  499.  
  500.     if (Data07 IN AdrModeA) {        /* Data in 0-7 (MOVEQ) */
  501.     quick = TRUE;
  502.     Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
  503.     if (Src.Mode != Imm)
  504.         Error (SrcLoc, ModeErr);
  505.     else if (Dest.Mode != DReg)
  506.         Error (DestLoc, ModeErr);
  507.     else if ((Src.Value < -128) || (Src.Value > 127))
  508.         Error (SrcLoc, SizeErr);
  509.     }
  510.  
  511.     if (Pass2) {
  512.     if (OpM68D IN AdrModeA) {    /* DReg in 6-8 (ADD/AND/OR/SUB) */
  513.         if (Dest.Mode == DReg) {
  514.         Op |= (Dest.Rn << 9);
  515.         if ((Src.Mode == ARDir) && (Size == Byte))
  516.             Error (SrcLoc, SizeErr);
  517.         } else /* Assume Src.Mode = DReg -- errors are trapped elsewhere. */
  518.         Op |= (Src.Rn << 9) | 0x0100;
  519.  
  520.         if (Size == Word) Op |= 0x0040;
  521.         if (Size == Long) Op |= 0x0080;
  522.     }
  523.  
  524.     if (OpM68A IN AdrModeA) {    /* AReg in 6-8 (ADDA/CMPA/SUBA) */
  525.         if (Dest.Mode == ARDir)
  526.         Op |= (Dest.Rn << 9);
  527.         else
  528.         Error (DestLoc, ModeErr);
  529.  
  530.         if (Size == Byte) Error (OpLoc+5, SizeErr);
  531.         if (Size == Word) Op |= 0x00C0;
  532.         if (Size == Long) Op |= 0x01C0;
  533.     }
  534.  
  535.     if (OpM68C IN AdrModeA) {    /* CMP (Compare) */
  536.         if (Dest.Mode == DReg)
  537.         Op |= (Dest.Rn << 9);
  538.         else
  539.         Error (DestLoc, ModeErr);
  540.  
  541.         if (Size == Byte) {
  542.         if (Src.Mode == ARDir)
  543.             Error (OpLoc+4, SizeErr);
  544.         }
  545.         if (Size == Word) Op |= 0x0040;
  546.         if (Size == Long) Op |= 0x0080;
  547.     }
  548.  
  549.     if (OpM68X IN AdrModeA) {    /* EOR (Exclusive or) */
  550.         if (Src.Mode == DReg)
  551.         Op |= (Src.Rn << 9);
  552.         else
  553.         Error (SrcLoc, ModeErr);
  554.  
  555.         if (Size == Byte) Op |= 0x0100;
  556.         if (Size == Word) Op |= 0x0140;
  557.         if (Size == Long) Op |= 0x0180;
  558.     }
  559.  
  560.     if (OpM68S IN AdrModeA) {    /* EXT (Sign extension) */
  561.         if (Src.Mode == DReg)
  562.         Op |= Src.Rn;
  563.         else
  564.         Error (SrcLoc, ModeErr);
  565.  
  566.         if (Dest.Mode != Null)
  567.         Error (DestLoc, OperErr);
  568.  
  569.         if (Size == Byte) Error (OpLoc+4, SizeErr);
  570.         if (Size == Word) Op |= 0x0080;
  571.         if (Size == Long) Op |= 0x00C0;
  572.     }
  573.  
  574.     if (OpM68R IN AdrModeA) {    /* MOVEP (Register/memory) */
  575.         if ((Src.Mode == DReg) && (Dest.Mode == ARDisp)) {
  576.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  577.         if (Size == Word) Op |= 0x0180;
  578.         if (Size == Long) Op |= 0x01C0;
  579.         Op |= (Src.Rn << 9) | Dest.Rn;
  580.         } else if ((Src.Mode == ARDisp) && (Dest.Mode == DReg)) {
  581.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  582.         if (Size == Word) Op |= 0x0100;
  583.         if (Size == Long) Op |= 0x0140;
  584.         Op |= Src.Rn | (Dest.Rn << 9);
  585.         } else
  586.         Error (SrcLoc, ModeErr);
  587.     }
  588.  
  589.     if (OpM37 IN AdrModeA) {    /* EXG (Exchange registers) */
  590.         if ((Src.Mode == DReg) && (Dest.Mode == DReg))
  591.         Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
  592.         else if ((Src.Mode == ARDir) && (Dest.Mode == ARDir))
  593.         Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
  594.         else if ((Src.Mode == ARDir) && (Dest.Mode == DReg))
  595.         Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn;
  596.         else if ((Src.Mode == DReg) && (Dest.Mode == ARDir))
  597.         Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
  598.         else
  599.         Error (SrcLoc, ModeErr);
  600.     }
  601.  
  602.     if (Bit811 IN AdrModeB) {    /* Bit operations using bits 8-11 */
  603.         if (Src.Mode == DReg)
  604.         Op |= 0x0100 | (Src.Rn << 9);
  605.         else if (Src.Mode == Imm)
  606.         Op |= 0x0800;
  607.         else
  608.         Error (SrcLoc, ModeErr);
  609.     }
  610.  
  611.     if (Size67 IN AdrModeB) {    /* Size in bits 6-7 */
  612.      /* if (Size == Byte) ; No action -- bits are already zero. */
  613.         if (Size == Word) Op |= 0x0040;
  614.         if (Size == Long) Op |= 0x0080;
  615.     }
  616.  
  617.     if (Size6 IN AdrModeB) {    /* Size in bit 6 (MOVEM) */
  618.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  619.      /* if (Size == Word) ; No action -- bit is already zero. */
  620.         if (Size == Long) Op |= 0x0040;
  621.     }
  622.  
  623.     if (Sz1213A IN AdrModeB) {    /* Size in 12-13 (MOVE) */
  624.         if (Size == Byte) Op |= 0x1000;
  625.         if (Size == Word) Op |= 0x3000;
  626.         if (Size == Long) Op |= 0x2000;
  627.     }
  628.  
  629.     if (Sz1213 IN AdrModeB) {    /* Size in 12-13 (MOVEA) */
  630.         if (Dest.Mode == DReg)    /* Can't be to adata register! */
  631.         Error(DestLoc,ModeErr);    /* (Others are caught elsewhere). */
  632.         Op |= (Dest.Rn << 9);
  633.         if (Size == Byte) Error (OpLoc+6, SizeErr);
  634.         if (Size == Word) Op |= 0x3000;
  635.         if (Size == Long) Op |= 0x2000;
  636.     }
  637.  
  638.     if (EA05a IN AdrModeB)        /* Effective address - all */
  639.         if ((Dest.Mode == DReg) || (Dest.Mode == ARDir))
  640.         EffAdr (&Src, ea);
  641.         else
  642.         Error (DestLoc, ModeErr);
  643.  
  644.     if (EA05b IN AdrModeB)    /* Eff. Addr. - all except ARDir */
  645.         if (Dest.Mode == DReg) {
  646.         EffAdr (&Src, dea);
  647.         Op |= (Dest.Rn << 9);
  648.         } else
  649.         Error (DestLoc, ModeErr);
  650.  
  651.     if (EA05c IN AdrModeB)        /* BTST */
  652.         if (Src.Mode == DReg)
  653.         EffAdr (&Dest, 0x0002);    /* All but ARDir */
  654.         else
  655.         EffAdr (&Dest, 0x0802);    /* All but ARDir/Imm */
  656.  
  657.     if(EA05d IN AdrModeB) {    /* All but PC relative & immediate */
  658.         EffAdr (&Dest, aea);
  659.         if ((Dest.Mode == ARDir) && (Size == Byte))
  660.         Error (OpLoc+5, SizeErr);
  661.     }
  662.  
  663.     if(EA05e IN AdrModeB) {    /* All but ARDir, PC relative, Imm */
  664.         if (Dest.Mode == Null)
  665.         EffAdr (&Src, (dea | aea));
  666.         else if (Src.Mode == Imm)
  667.         EffAdr (&Dest, (dea | aea));
  668.         else if (Src.Mode == DReg) {
  669.         if (AdrModeB == (Size67 | EA05e | Exten))
  670.             Error (SrcLoc, ModeErr);
  671.         EffAdr (&Dest, (dea | aea));
  672.         } else
  673.         Error (SrcLoc, ModeErr);
  674.     }
  675.  
  676.     if (EA05f IN AdrModeB) {    /* JMP, JSR, LEA, and PEA */
  677.         EffAdr (&Src, cea);
  678.         if (Rx911 IN AdrModeA)
  679.         if (Dest.Mode == ARDir)
  680.             Op |= (Dest.Rn << 9);   /* Address Reg. for LEA */
  681.         else
  682.             Error(DestLoc,ModeErr); /* Must load Address Reg. */
  683.         else
  684.         if (Dest.Mode != Null)
  685.             Error (DestLoc, OperErr);    /* No Dest. unless LEA */
  686.     }
  687.  
  688.     if (EA05x IN AdrModeB) {    /* AND and OR */
  689.         if (Dest.Mode == DReg)
  690.         EffAdr (&Src, dea);
  691.         else if (Src.Mode == DReg)
  692.         EffAdr (&Dest, mea | aea);
  693.         else
  694.         Error (SrcLoc, OperErr);
  695.     }
  696.  
  697.     if (EA05y IN AdrModeB) {    /* ADD and SUB */
  698.         if (Dest.Mode == DReg) {
  699.         EffAdr (&Src, ea);
  700.         if ((Src.Mode == ARDir) && (Size == Byte))
  701.             Error (OpLoc+4, SizeErr);
  702.         } else if (Src.Mode == DReg)
  703.         EffAdr (&Dest, (mea | aea));
  704.         else
  705.         Error (SrcLoc, ModeErr);
  706.     }
  707.     }
  708.  
  709.     if (EA05z IN AdrModeB) {        /* MOVEM */
  710.     if (Pass2) {
  711.         if (Src.Mode == MultiM) {        /* Move to memory. */
  712.         EffAdr (&Dest, (mea | aea | 0x0008));
  713.         ExtL = Src.Value;
  714.         i = (Dest.Mode == ARPre);    /* ExtL flip indicator */
  715.         } else if (Dest.Mode == MultiM) {    /* Move from memory. */
  716.         Op |= 0x0400;            /* Set direction. */
  717.         EffAdr (&Src, (mea | 0x0810));
  718.         ExtL = Dest.Value;
  719.         i = (Src.Mode == ARPre);
  720.         } else {
  721.         Error (SrcLoc, OperErr);
  722.         i = FALSE;
  723.         }
  724.         if (i) {                /* Flip ExtL if ARPre. */
  725.         j = 0;
  726.         for (i = 0; i < 8; i++)
  727.             j |= (ExtL & (1<<i)) << (15-i*2);
  728.         for (i = 8; i < 16; i++)
  729.             j |= (ExtL & (1<<i)) >> (i*2-15);
  730.         ExtL = j;
  731.         }
  732.     }
  733.     nO += 2;    /* Extension is part of OpCode. */
  734.     InstSize += 2;
  735.     }
  736.  
  737.     if (Pass2) {
  738.  
  739.     if (EA611 IN AdrModeB) {    /* Eff. Addr. in 6-11 (MOVE) */
  740.         if (Dest.Mode == CCR) {        /* MOVE to CCR */
  741.         Op = 0x44C0;
  742.         EffAdr (&Src, dea);
  743.         } else if (Dest.Mode == SR) {    /* MOVE to SR */
  744.         Op = 0x46C0;
  745.         EffAdr (&Src, dea);
  746.         } else if (Src.Mode    == SR) {    /* MOVE from SR */
  747.         Op = 0x40C0;
  748.         EffAdr (&Dest, dea | aea);
  749.         } else if (Dest.Mode == USP) {    /* MOVE to USP */
  750.         Op = 0x4E60;
  751.         if (Src.Mode == ARDir)
  752.             Op |= Src.Rn;
  753.         else
  754.             Error (SrcLoc, ModeErr);
  755.         } else if (Src.Mode == USP) {    /* MOVE from USP */
  756.         Op = 0x4E68;
  757.         if (Dest.Mode == ARDir)
  758.             Op |= Dest.Rn;
  759.         else
  760.             Error (DestLoc, ModeErr);
  761.         } else {            /* General MOVE instruction */
  762.         EffAdr (&Src, (ea | xxx));
  763.         if ((Size == Byte) && (Src.Mode == ARDir))
  764.             Error (SrcLoc, SizeErr);
  765.         if (Src.Mode > 12)
  766.             Error (SrcLoc, ModeErr);
  767.         if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12))
  768.             Error (DestLoc, ModeErr);
  769.         else if (Dest.Mode < 8)    /* Register direct or indirect */
  770.             Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn << 9);
  771.         else        /* Absolute, PC relative, or immediate */
  772.             Op |= 0x01C0 | ((Dest.Mode - 8) << 9);
  773.         OperExt (&Dest);        /* Set up extension word. */
  774.         }
  775.     }
  776.  
  777.     if ((Dest.Mode == CCR) && (Src.Mode == Imm)) {
  778.         if ((Size67 IN AdrModeB)
  779.         && (EA05e IN AdrModeB)
  780.         && (Exten IN AdrModeB))
  781.         if (0x0400 IN Op)    /* not ANDI/EORI/ORI */
  782.             Error (DestLoc, ModeErr);
  783.         else
  784.             Op = (Op & 0xFF00) | 0x003C;
  785.     }
  786.  
  787.     if ((Dest.Mode == SR) && (Src.Mode == Imm)) {
  788.         if ((Size67 IN AdrModeB)
  789.         && (EA05e IN AdrModeB)
  790.         && (Exten IN AdrModeB))
  791.         if (0x0400 IN Op)    /* not ANDI/EORI/ORI */
  792.             Error (DestLoc, ModeErr);
  793.         else
  794.             Op = (Op & 0xFF00) | 0x007C;
  795.     }
  796.     }
  797.  
  798.     ObjOp = Op;
  799.     InstSize += 2;
  800.     nO += 2;
  801.     if (nO > 2) {
  802.     templong = ExtL;            /* Add extension word. */
  803.     ObjOp = (ObjOp << 16) | (templong & 0x0000FFFFL);
  804.     }
  805.     if ((AdrModeA != 0) || (AdrModeB != 0)) {
  806.     InstSize += (nS = GetInstModeSize (Src.Mode));
  807.     ObjSrc = Src.Value;
  808.     if ((Src.Mode == Imm) && (Size == Byte))
  809.         ObjSrc &= 0xFF;    /* Pad a byte value with zeros. */
  810.     InstSize += (nD = GetInstModeSize (Dest.Mode));
  811.     ObjDest = Dest.Value;
  812.     }
  813.     if (quick) {
  814.     InstSize -= nS;        /* Source operand is in Op. */
  815.     nS = 0;
  816.     }
  817.  
  818.     if (Pass2) {
  819.     if ((nS!=0) && (Src.Hunk!=ABSHUNK)) {    /* SrcOp is relocatable. */
  820.         if ((Src.Mode == AbsL)
  821.         || (Src.Mode == AbsW)
  822.         || (Src.Mode == ARDisp)
  823.         || (Src.Mode == PCDisp)
  824.         || (Src.Mode == Imm)) {
  825.         templong = AddrCnt+nO;    /* 32- or 16-bit relocatable */
  826.         PutRel (templong, Src.Hunk, nS);
  827.         }
  828.         if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
  829.         templong = AddrCnt + nO + 1;    /* 8-bit relocatable */
  830.         PutRel (templong, Src.Hunk, 1);
  831.         }
  832.     }
  833.     if ((nD!=0) && (Dest.Hunk!=ABSHUNK)) {    /* DestOp is relocatable. */
  834.         if ((Dest.Mode == AbsL)
  835.         || (Dest.Mode == AbsW)
  836.         || (Dest.Mode == ARDisp)
  837.         || (Dest.Mode == PCDisp)
  838.         || (Dest.Mode == Imm)) {
  839.         templong = AddrCnt+nO+nS; /* 32- or 16-bit relocatable */
  840.         PutRel (templong, Dest.Hunk, nD);
  841.         }
  842.         if ((Dest.Mode==ARDisX) || (Dest.Mode==PCDisX)) {
  843.         templong = AddrCnt+nO+nS+1;    /* 8-bit relocatable */
  844.         PutRel (templong, Dest.Hunk, 1);
  845.         }
  846.     }
  847.     }
  848.     AddrAdv = InstSize;
  849. }
  850.  
  851.  
  852.  
  853. void PackFwdBranch (dummy) int dummy;
  854. /* Drops expired entries (more than 128 bytes old)
  855.     from the forward branch optimization candidate table
  856.     and the label fixup table.                */
  857. {
  858.     register struct FwdBr *fp1, *fp2;
  859.     register struct SymTab **fsp, **fsp2, **fsp3;
  860.  
  861.     fp2 = FwdBranch;
  862.     while ((fp2 < FwdLim1) && (fp2->Loc < (AddrCnt - 128)))
  863.     fp2++;            /* Find the first unexpired entry. */
  864.  
  865.     if (fp2 > FwdBranch) {        /* If we can drop anything, */
  866.     fp1 = FwdBranch;        /*  shift active entries    */
  867.     while (fp2 < FwdLim1) {        /*  over expired ones.      */
  868.         fp1->Loc    = fp2->Loc;
  869.         fp1->FwdSym = fp2->FwdSym;
  870.         fp1->Line   = fp2->Line;
  871.         fp1++;
  872.         fp2++;
  873.     }
  874.     FwdLim1 = fp1;    /* The table now ends here. */
  875.     }
  876.  
  877.     if (FwdLim1 <= FwdBranch)
  878.     FwdFixLimit = FwdBranchFix;    /* No outstanding branches */
  879.  
  880.     for (fsp = FwdBranchFix; fsp < FwdFixLimit; fsp++) {
  881.     if ((*fsp)->Val < (AddrCnt - 128)) {
  882.         fsp2 = fsp3 = fsp;        /* Now drop expired label entries. */
  883.         fsp3++;
  884.         while (fsp3 < FwdFixLimit)
  885.         *fsp2++ = *fsp3++;
  886.         FwdFixLimit--;
  887.     }
  888.     }
  889. }
  890.